<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2020/5/23 0023
 * Time: 16:07
 */

namespace Api\Controller;


use Api\Service\FileService;
use Api\Service\WechatService;

class OrderController extends BaseController
{
    protected $mid;
    protected $member;
    public function __construct()
    {
        parent::__construct();
        //验证用户
        $openid = I('request.openid','');
        empty($openid) && $this->error('openid缺失！');
        $member = M('Usermember')->where(['openid' => $openid])->find();
        empty($member) && $this->error('用户不存在！');
        $this->mid = $member['id'];
        $this->member = $member;
    }

    /**
     * 查询投放广告列表
     */
    public function index()
    {
        $list = M('AdOrder')->where(['mid' => $this->mid])->select();
        $order_list = M('AdOrderList')->where(['order_no' => array('in',array_unique(array_column($list,'order_no')))])->select();
        foreach ($list as &$item){
            $item['list'] = [];
            foreach ($order_list as $order) if($item['order_no'] === $order['order_no']) {
                $order['qrcode_path'] = SITE_URL . $order['qrcode_path'];
                $item['list'][] = $order;
            }
        }
        $this->success('获取投放广告列表成功！',$list);
    }
    /**
     * 查询投放广告详情
     * @param $id3
     */
    public function read($id)
    {
        $order = M('AdOrder')->where(['mid' => $this->mid,'order_no' => $id])->find();
        empty($order) && $this->error('查询订单信息失败！');
        $order_list = M('AdOrderList')->where(['order_no' => $id])->select();
        $order['list'] = [];
        foreach ($order_list as &$item) {
            $item['qrcode_path'] = SITE_URL . $item['qrcode_path'];
        }
        $order['list'] = $order_list;
        $this->success('获取订单详情成功！',$order);
    }

    /**
     * 发布广告
     * @throws \WeChat\Exceptions\InvalidResponseException
     * @throws \WeChat\Exceptions\LocalCacheException
     * @throws \think\Exception
     */
    public function save()
    {
        $self_shop = M('Shop')->where(['user_id' => $this->mid,'status' => '2'])->find();
        empty($self_shop) && $this->error('请求错误！');

        $ad_type = I('post.ad_type');// 广告类型： 1曝光 2引流
        if(!in_array($ad_type,['1','2'])) $ad_type = '1';

        $ad_resource_type = I('post.ad_resource_type');// 广告资源类型 1图片 2视频
        if(!in_array($ad_resource_type,['1','2'])) $ad_resource_type = '1';

        $resource_id = I('post.resource_id');// 广告资源ID
        is_numeric($resource_id) || $resource_id = 0;

        $subtitle = I('post.subtitle');// 广告字幕

        $start_time = I('post.start_time');// 开始时间
        $end_time = I('post.end_time');// 结束时间
        if(valid_date($start_time) === false){
            $this->error('请输入正确的开始时间！');
        }
        if(valid_date($end_time) === false){
            $this->error('请输入正确的结束时间！');
        }
        if(strtotime($start_time) >= strtotime($end_time)){
            $this->error('结束时间必须大于开始时间！');
        }
        $diffBetweenTwoDays = diffBetweenTwoDays($start_time,$end_time);
        //转化为时间戳
        $start_time = strtotime($start_time);
        $end_time = strtotime($end_time);

        $red_packet_num = I('post.red_packet_num');//红包个数
        $red_packet_moeny = I('post.red_packet_moeny');//单个红包金额
        is_numeric($red_packet_num) || $red_packet_num = 0;
        is_numeric($red_packet_moeny) || $red_packet_moeny = 0;
        // 红包数量及金额限制
        if($ad_type == '2'){
            if($red_packet_num < C('MIN_RED_NUMBER')){
                $this->error('单个广告最低红包数量：'.C('MIN_RED_NUMBER'));
            }
            if($red_packet_moeny < C('MIN_RED_MONEY')) {
                $this->error('单个红包最低金额：'.C('MIN_RED_MONEY'));
            }
            if($diffBetweenTwoDays < C('IN_LIMIT_DAY')){
                $this->error('定向引流最低天数：'.C('IN_LIMIT_DAY'));
            }
        } else {
            if($diffBetweenTwoDays < C('UP_LIMIT_DAY')){
                $this->error('定向曝光最低天数：'.C('UP_LIMIT_DAY'));
            }
        }
        $distance_is_user = I('post.distance_is_user');//是否以自己作为距离计算起点
        $distance = I('post.distance');//领取红包距离限制 为0则不限制
        is_numeric($distance) || $distance = 0;

        $screen_id = I('post.screen_id');//投放屏幕ID集合 “,”分割
        $screen_id = array_filter(explode(',',$screen_id));
        empty($screen_id) && $this->error('请选择投放屏幕！');
        $pay_type = I('post.pay_type');
        if(!in_array($pay_type,['wechat','balance'])){
            $pay_type = 'wechat';
        }
        //组装订单数据
        $order_no = uniqidNumberCode(12);
        $order = [
            'mid' => $this->mid,
            'order_no' => $order_no,
            'ad_type' => $ad_type,
            'ad_resource_type' => $ad_resource_type,
            'resource_id' => $resource_id,
            'subtitle' => $subtitle,
            'red_packet_num' => $red_packet_num,
            'red_packet_moeny' => $red_packet_moeny,
            'start_time' => $start_time,
            'end_time' => $end_time,
            'pay_type' => $pay_type,
            'pay_state' => '0'
        ];
        $order_list = [];
        foreach ($screen_id as $screen){
            $screen_id = uniqidNumberCode(10);
            $shop_store_screen = M('ShopStoreScreen')->where(['id' => $screen,'status' => '1'])->find();
            empty($shop_store_screen) && $this->error('查询分屏信息错误！');
            $shop_store = M('ShopStore')->where(['id' => $shop_store_screen['sid'],'status' => '1'])->find();
            empty($shop_store) && $this->error('查询店铺信息错误！');
            $shop = M('Shop')->where(['id' => $shop_store['sid'],'status' => '2'])->find();
            empty($shop) && $this->error('查询商家信息错误！');
            if($shop['id'] == $self_shop['id']){
                $this->error('不能投自己的店铺！');
            }
            $qrcode_path = '';
            //价格计算
            if($ad_type == '1'){
                $screen_price = C('PUT_MONEY') * $diffBetweenTwoDays;
            } else {
                $screen_price = $red_packet_num * $red_packet_moeny;
                //生成红包二维码
                $page = "pages/user/adv_detail/adv_detail";
                $qr_code = WechatService::WeMiniQrcode()->createMiniScene("pid={$screen_id}",$page);
                $qr_code_filename = "qrcode/qrcode-{$screen_id}.jpeg";
                $file = new FileService();
                //二维码保存到本地
                $info = $file->save($qr_code_filename, $qr_code);
                //保存失败
                if (!is_array($info) || !isset($info['url'])) {
                    http_response_code(404);
                    $this->error('生成二维码失败！');
                }
                $qrcode_path = $file->path($qr_code_filename);
            }

            $order_list[] = [
                'id' => $screen_id,
                'mid' => $this->mid,
                'order_no' => $order_no,
                'screen_id' => $screen,
                'store_id' => $shop_store['id'],
                'shop_id' => $shop['id'],
                'red_packet_num' => $red_packet_num,
                'red_packet_moeny' => $red_packet_moeny,
                'start_time' => $start_time,
                'end_time' => $end_time,
                'price' => $screen_price,
                'ad_type' => $ad_type,
                'qrcode_path' => $qrcode_path,
                'distance' => $distance,
                'lat' => $distance_is_user ? $self_shop['latitude'] : $shop_store['lat'],
                'lng' => $distance_is_user ? $self_shop['longitude'] : $shop_store['lng'],
            ];
            $order['total_price'] += $screen_price;
//            dump($shop_store);
        }

        M()->startTrans();// 开启事务
        $add_order_list = M('AdOrderList')->addAll($order_list);
        $user_pay = true;
        // 如果用户选择余额支付
        if($pay_type == 'balance'){
            $self_use_balance = $self_shop['shop_balance'];
            if($ad_type == '1'){
                $self_use_balance = $self_shop['exposure_balance'];
            }
            if($order['total_price'] > $self_use_balance){
                $this->error('余额不足！');
            }
            $order['pay_state'] = '1';
            $order['pay_at'] = date('Y-m-d H:i:s');
            $user_pay_data = [
                'balance' => $self_shop['balance'] - $order['total_price'],
                'shop_balance' => $self_shop['shop_balance'] - $order['total_price'],
            ];
            // 优先使用可用于引流和曝光的余额
            // 如果消费之后可用于引流和曝光的余额小于仅可用于曝光的余额，则把仅可用于曝光的余额缩减至对应值
            if($user_pay_data['shop_balance'] < $self_shop['exposure_balance']){
                $user_pay_data['exposure_balance'] = $user_pay_data['shop_balance'];
            }
            // 如果投递的是曝光广告
            if($ad_type == '1'){
                $user_pay_data['exposure_balance'] = $self_shop['exposure_balance'] - $order['total_price'];
            }
            // 优先使用不可用于提现的部分余额
            // 如果消费之后总余额或仅可用于曝光的余额小于可提现余额，缩减可提现余额至对应值
            if(min($user_pay_data['balance'],$user_pay_data['exposure_balance']) < $self_shop['withdraw_balance']){
                $user_pay_data['withdraw_balance'] = min($user_pay_data['balance'],$user_pay_data['exposure_balance']);
            }
            $user_pay = M('Shop')->where(['id' => $self_shop['id']])->save($user_pay_data);
        }
        $add_order = M('AdOrder')->add($order);
        if($add_order !== false && $add_order_list !== false && $user_pay !== false){
            M()->commit();
            $this->success('创建订单成功！',['pay_type' => $pay_type,'pay_state' => $order['pay_state'],'order_no' => $order_no,'payParams' => $this->getPayParams($order_no, $order['total_price'], $this->member['openid'], $order['pay_state'])]);
        } else {
            M()->rollback();
            $this->error('创建订单失败！');
        }
    }

    /**
     * 生成支付参数
     * 支付参数统一放在后台配置的，如需改动请直接在后台修改配置参数
     * @param $order_no string 订单号码
     * @param $pay_price string|float|integer 订单金额
     * @param $openid string openid
     * @param string $pay_state
     * @return array|bool|null
     */
    protected function getPayParams($order_no, $pay_price, $openid, $pay_state = '0'){
        if($pay_state == '1'){
            return null;
        }
        //生成支付参数
        $options = [
            'body'             => '商城订单支付',
            'openid'           => $openid,
            'out_trade_no'     => $order_no,
            'total_fee'        => $pay_price * 100,
            'trade_type'       => 'JSAPI',
//            'notify_url'       => U('api/notify/wxpay', '', false, true),
            'notify_url'       => 'http://www.lianxiang.com/api/notify/wxpay',
            'spbill_create_ip' => getip(),
        ];
        try {
            $pay = WechatService::WePayOrder();
            $info = $pay->create($options);
            if ($info['return_code'] === 'SUCCESS' && $info['result_code'] === 'SUCCESS') {
                return $pay->jsapiParams($info['prepay_id']);
            }
            if (isset($info['err_code_des'])) {
                throw new \think\Exception($info['err_code_des']);
            }
            throw new \think\Exception('未知错误！');
        } catch (\Exception $e) {
            $this->error("创建订单支付参数失败，{$e->getMessage()}",'',206);
        }
        return true;
    }

    /**
     * 发起支付
     */
    public function pay()
    {
        $order_no = I('post.order_no');
        empty($order_no) && $this->error('请求错误！');
        $order = M('AdOrder')->where(['mid' => $this->mid,'order_no' => $order_no])->find();
        empty($order) && $this->error('查询订单失败！');
        if($order['pay_state'] == '1'){
            $this->error('此订单状态不允许支付~');
        }
        // 开始生成支付参数
        $this->success('生成订单支付参数成功！',['payParams' => $this->getPayParams($order_no, $order['total_price'], $this->member['openid'])]);
    }

    /**
     * 设置订单支付成功
     */
    public function paySuccess()
    {
        $order_no = I('post.order_no');
        $data = [
            'pay_state' => '1',
            'pay_at' => date('Y-m-d H:i:s')
        ];
        $res = M('AdOrder')->where(['mid' => $this->mid,'order_no' => $order_no, 'pay_state' => '0'])->save($data);
        if($res !== false){
            $this->success('设置成功！');
        } else {
            $this->error('设置失败！');
        }
    }
}